/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Rockchip Vehicle driver
 *
 * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
 */

#ifndef _VEHICLE_CSI2_DPHY_COMMON_H_
#define _VEHICLE_CSI2_DPHY_COMMON_H_

#include <linux/kernel.h>
#include <linux/rk-camera-module.h>
#include <media/v4l2-subdev.h>
#include "vehicle_samsung_dcphy_common.h"
#include "../../../media/platform/rockchip/cif/mipi-csi2.h"

/* RK3562 DPHY GRF REG OFFSET */
#define RK3562_GRF_VI_CON0	(0x0520)
#define RK3562_GRF_VI_CON1	(0x0524)

/* GRF REG OFFSET */
#define GRF_VI_CON0	(0x0340)
#define GRF_VI_CON1	(0x0344)

/*RK3588 DPHY GRF REG OFFSET */
#define GRF_DPHY_CON0	(0x0)
#define GRF_SOC_CON2	(0x0308)

/*GRF REG BIT DEFINE */
#define GRF_CSI2PHY_LANE_SEL_SPLIT	(0x1)
#define GRF_CSI2PHY_SEL_SPLIT_0_1	(0x0)
#define GRF_CSI2PHY_SEL_SPLIT_2_3	BIT(0)

/*RK3588 DCPHY GRF REG OFFSET */
#define GRF_DCPHY_CON0			(0x0)

/* PHY REG OFFSET */
#define CSI2_DPHY_CTRL_INVALID_OFFSET	(0xffff)
#define CSI2_DPHY_CTRL_PWRCTL	\
				CSI2_DPHY_CTRL_INVALID_OFFSET
#define CSI2_DPHY_CTRL_LANE_ENABLE	(0x00)
#define CSI2_DPHY_CLK1_LANE_EN		(0x2C)
#define CSI2_DPHY_DUAL_CAL_EN		(0x80)
#define CSI2_DPHY_CLK_WR_THS_SETTLE	(0x160)
#define CSI2_DPHY_CLK_CALIB_EN		(0x168)
#define CSI2_DPHY_LANE0_WR_THS_SETTLE	(0x1e0)
#define CSI2_DPHY_LANE0_CALIB_EN	(0x1e8)
#define CSI2_DPHY_LANE1_WR_THS_SETTLE	(0x260)
#define CSI2_DPHY_LANE1_CALIB_EN	(0x268)
#define CSI2_DPHY_LANE2_WR_THS_SETTLE	(0x2e0)
#define CSI2_DPHY_LANE2_CALIB_EN	(0x2e8)
#define CSI2_DPHY_LANE3_WR_THS_SETTLE	(0x360)
#define CSI2_DPHY_LANE3_CALIB_EN	(0x368)
#define CSI2_DPHY_CLK1_WR_THS_SETTLE	(0x3e0)
#define CSI2_DPHY_CLK1_CALIB_EN		(0x3e8)

//DCPHY
#define CSI2_DCPHY_CLK_WR_THS_SETTLE		(0x030)
#define CSI2_DCPHY_LANE0_WR_THS_SETTLE		(0x130)
#define CSI2_DCPHY_LANE0_WR_ERR_SOT_SYNC	(0x134)
#define CSI2_DCPHY_LANE1_WR_THS_SETTLE		(0x230)
#define CSI2_DCPHY_LANE1_WR_ERR_SOT_SYNC	(0x234)
#define CSI2_DCPHY_LANE2_WR_THS_SETTLE		(0x330)
#define CSI2_DCPHY_LANE2_WR_ERR_SOT_SYNC	(0x334)
#define CSI2_DCPHY_LANE3_WR_THS_SETTLE		(0x430)
#define CSI2_DCPHY_LANE3_WR_ERR_SOT_SYNC	(0x434)
#define CSI2_DCPHY_CLK_LANE_ENABLE		(0x000)
#define CSI2_DCPHY_DATA_LANE0_ENABLE		(0x100)
#define CSI2_DCPHY_DATA_LANE1_ENABLE		(0x200)
#define CSI2_DCPHY_DATA_LANE2_ENABLE		(0x300)
#define CSI2_DCPHY_DATA_LANE3_ENABLE		(0x400)

#define CSI2_DCPHY_S0C_GNR_CON1                 (0x004)
#define CSI2_DCPHY_S0C_ANA_CON1			(0x00c)
#define CSI2_DCPHY_S0C_ANA_CON2			(0x010)
#define CSI2_DCPHY_S0C_ANA_CON3			(0x014)
#define CSI2_DCPHY_COMBO_S0D0_GNR_CON1          (0x104)
#define CSI2_DCPHY_COMBO_S0D0_ANA_CON1		(0x10c)
#define CSI2_DCPHY_COMBO_S0D0_ANA_CON2		(0x110)
#define CSI2_DCPHY_COMBO_S0D0_ANA_CON3		(0x114)
#define CSI2_DCPHY_COMBO_S0D0_ANA_CON6		(0x120)
#define CSI2_DCPHY_COMBO_S0D0_ANA_CON7		(0x124)
#define CSI2_DCPHY_COMBO_S0D0_DESKEW_CON0	(0x140)
#define CSI2_DCPHY_COMBO_S0D0_DESKEW_CON2	(0x148)
#define CSI2_DCPHY_COMBO_S0D0_DESKEW_CON4	(0x150)
#define CSI2_DCPHY_COMBO_S0D0_CRC_CON1		(0x164)
#define CSI2_DCPHY_COMBO_S0D0_CRC_CON2		(0x168)
#define CSI2_DCPHY_COMBO_S0D1_GNR_CON1          (0x204)
#define CSI2_DCPHY_COMBO_S0D1_ANA_CON1		(0x20c)
#define CSI2_DCPHY_COMBO_S0D1_ANA_CON2		(0x210)
#define CSI2_DCPHY_COMBO_S0D1_ANA_CON3		(0x214)
#define CSI2_DCPHY_COMBO_S0D1_ANA_CON6		(0x220)
#define CSI2_DCPHY_COMBO_S0D1_ANA_CON7		(0x224)
#define CSI2_DCPHY_COMBO_S0D1_DESKEW_CON0	(0x240)
#define CSI2_DCPHY_COMBO_S0D1_DESKEW_CON2	(0x248)
#define CSI2_DCPHY_COMBO_S0D1_DESKEW_CON4	(0x250)
#define CSI2_DCPHY_COMBO_S0D1_CRC_CON1		(0x264)
#define CSI2_DCPHY_COMBO_S0D1_CRC_CON2		(0x268)
#define CSI2_DCPHY_COMBO_S0D2_GNR_CON1          (0x304)
#define CSI2_DCPHY_COMBO_S0D2_ANA_CON1		(0x30c)
#define CSI2_DCPHY_COMBO_S0D2_ANA_CON2		(0x310)
#define CSI2_DCPHY_COMBO_S0D2_ANA_CON3		(0x314)
#define CSI2_DCPHY_COMBO_S0D2_ANA_CON6		(0x320)
#define CSI2_DCPHY_COMBO_S0D2_ANA_CON7		(0x324)
#define CSI2_DCPHY_COMBO_S0D2_DESKEW_CON0	(0x340)
#define CSI2_DCPHY_COMBO_S0D2_DESKEW_CON2	(0x348)
#define CSI2_DCPHY_COMBO_S0D2_DESKEW_CON4	(0x350)
#define CSI2_DCPHY_COMBO_S0D2_CRC_CON1		(0x364)
#define CSI2_DCPHY_COMBO_S0D2_CRC_CON2		(0x368)
#define CSI2_DCPHY_S0D3_GNR_CON1                (0x404)
#define CSI2_DCPHY_S0D3_ANA_CON1		(0x40c)
#define CSI2_DCPHY_S0D3_ANA_CON2		(0x410)
#define CSI2_DCPHY_S0D3_ANA_CON3		(0x414)
#define CSI2_DCPHY_S0D3_DESKEW_CON0		(0x440)
#define CSI2_DCPHY_S0D3_DESKEW_CON2		(0x448)
#define CSI2_DCPHY_S0D3_DESKEW_CON4		(0x450)

/* PHY REG BIT DEFINE */
#define CSI2_DPHY_LANE_MODE_FULL	(0x4)
#define CSI2_DPHY_LANE_MODE_SPLIT	(0x2)
#define CSI2_DPHY_LANE_SPLIT_TOP	(0x1)
#define CSI2_DPHY_LANE_SPLIT_BOT	(0x2)
#define CSI2_DPHY_LANE_SPLIT_LANE0_1	(0x3 << 2)
#define CSI2_DPHY_LANE_SPLIT_LANE2_3	(0x3 << 4)
#define CSI2_DPHY_LANE_DUAL_MODE_EN	BIT(6)
#define CSI2_DPHY_LANE_PARA_ARR_NUM	(0x2)

#define CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT	2
#define CSI2_DPHY_CTRL_DATALANE_SPLIT_LANE2_3_OFFSET_BIT	4
#define CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT	6

enum csi2_dphy_index {
	DPHY0 = 0x0,
	DPHY1,
	DPHY2,
};

enum csi2_dphy_lane {
	CSI2_DPHY_LANE_CLOCK = 0,
	CSI2_DPHY_LANE_CLOCK1,
	CSI2_DPHY_LANE_DATA0,
	CSI2_DPHY_LANE_DATA1,
	CSI2_DPHY_LANE_DATA2,
	CSI2_DPHY_LANE_DATA3
};

enum grf_reg_id {
	GRF_DPHY_RX0_TURNDISABLE = 0,
	GRF_DPHY_RX0_FORCERXMODE,
	GRF_DPHY_RX0_FORCETXSTOPMODE,
	GRF_DPHY_RX0_ENABLE,
	GRF_DPHY_RX0_TESTCLR,
	GRF_DPHY_RX0_TESTCLK,
	GRF_DPHY_RX0_TESTEN,
	GRF_DPHY_RX0_TESTDIN,
	GRF_DPHY_RX0_TURNREQUEST,
	GRF_DPHY_RX0_TESTDOUT,
	GRF_DPHY_TX0_TURNDISABLE,
	GRF_DPHY_TX0_FORCERXMODE,
	GRF_DPHY_TX0_FORCETXSTOPMODE,
	GRF_DPHY_TX0_TURNREQUEST,
	GRF_DPHY_TX1RX1_TURNDISABLE,
	GRF_DPHY_TX1RX1_FORCERXMODE,
	GRF_DPHY_TX1RX1_FORCETXSTOPMODE,
	GRF_DPHY_TX1RX1_ENABLE,
	GRF_DPHY_TX1RX1_MASTERSLAVEZ,
	GRF_DPHY_TX1RX1_BASEDIR,
	GRF_DPHY_TX1RX1_ENABLECLK,
	GRF_DPHY_TX1RX1_TURNREQUEST,
	GRF_DPHY_RX1_SRC_SEL,
	/* rk3288 only */
	GRF_CON_DISABLE_ISP,
	GRF_CON_ISP_DPHY_SEL,
	GRF_DSI_CSI_TESTBUS_SEL,
	GRF_DVP_V18SEL,
	/* rk1808 & rk3326 & rv1126 */
	GRF_DPHY_CSI2PHY_FORCERXMODE,
	GRF_DPHY_CSI2PHY_CLKLANE_EN,
	GRF_DPHY_CSI2PHY_DATALANE_EN,
	/* rv1126 only */
	GRF_DPHY_CLK_INV_SEL,
	GRF_DPHY_SEL,
	/* rk3368 only */
	GRF_ISP_MIPI_CSI_HOST_SEL,
	/* below is for rk3399 only */
	GRF_DPHY_RX0_CLK_INV_SEL,
	GRF_DPHY_RX1_CLK_INV_SEL,
	GRF_DPHY_TX1RX1_SRC_SEL,
	/* below is for rk3568 only */
	GRF_DPHY_CSI2PHY_CLKLANE1_EN,
	GRF_DPHY_CLK1_INV_SEL,
	GRF_DPHY_ISP_CSI2PHY_SEL,
	GRF_DPHY_CIF_CSI2PHY_SEL,
	GRF_DPHY_CSI2PHY_LANE_SEL,
	GRF_DPHY_CSI2PHY1_LANE_SEL,
	GRF_DPHY_CSI2PHY_DATALANE_EN0,
	GRF_DPHY_CSI2PHY_DATALANE_EN1,
	GRF_CPHY_MODE,
	GRF_DPHY_CSIHOST2_SEL,
	GRF_DPHY_CSIHOST3_SEL,
	GRF_DPHY_CSIHOST4_SEL,
	GRF_DPHY_CSIHOST5_SEL,
	/* below is for rv1106 only */
	GRF_MIPI_HOST0_SEL,
	GRF_LVDS_HOST0_SEL,
	/* below is for rk3562 */
	GRF_DPHY1_CLK_INV_SEL,
	GRF_DPHY1_CLK1_INV_SEL,
	GRF_DPHY1_CSI2PHY_CLKLANE1_EN,
	GRF_DPHY1_CSI2PHY_FORCERXMODE,
	GRF_DPHY1_CSI2PHY_CLKLANE_EN,
	GRF_DPHY1_CSI2PHY_DATALANE_EN,
	GRF_DPHY1_CSI2PHY_DATALANE_EN0,
	GRF_DPHY1_CSI2PHY_DATALANE_EN1,
};

enum csi2dphy_reg_id {
	CSI2PHY_REG_CTRL_LANE_ENABLE = 0,
	CSI2PHY_CTRL_PWRCTL,
	CSI2PHY_CTRL_DIG_RST,
	CSI2PHY_CLK_THS_SETTLE,
	CSI2PHY_LANE0_THS_SETTLE,
	CSI2PHY_LANE1_THS_SETTLE,
	CSI2PHY_LANE2_THS_SETTLE,
	CSI2PHY_LANE3_THS_SETTLE,
	CSI2PHY_CLK_CALIB_ENABLE,
	CSI2PHY_LANE0_CALIB_ENABLE,
	CSI2PHY_LANE1_CALIB_ENABLE,
	CSI2PHY_LANE2_CALIB_ENABLE,
	CSI2PHY_LANE3_CALIB_ENABLE,
	//rv1126 only
	CSI2PHY_MIPI_LVDS_MODEL,
	CSI2PHY_LVDS_MODE,
	//rk3568 only
	CSI2PHY_DUAL_CLK_EN,
	CSI2PHY_CLK1_THS_SETTLE,
	CSI2PHY_CLK1_CALIB_ENABLE,
	//rk3588
	CSI2PHY_CLK_LANE_ENABLE,
	CSI2PHY_CLK1_LANE_ENABLE,
	CSI2PHY_DATA_LANE0_ENABLE,
	CSI2PHY_DATA_LANE1_ENABLE,
	CSI2PHY_DATA_LANE2_ENABLE,
	CSI2PHY_DATA_LANE3_ENABLE,
	CSI2PHY_LANE0_ERR_SOT_SYNC,
	CSI2PHY_LANE1_ERR_SOT_SYNC,
	CSI2PHY_LANE2_ERR_SOT_SYNC,
	CSI2PHY_LANE3_ERR_SOT_SYNC,
	CSI2PHY_S0C_GNR_CON1,
	CSI2PHY_S0C_ANA_CON1,
	CSI2PHY_S0C_ANA_CON2,
	CSI2PHY_S0C_ANA_CON3,
	CSI2PHY_COMBO_S0D0_GNR_CON1,
	CSI2PHY_COMBO_S0D0_ANA_CON1,
	CSI2PHY_COMBO_S0D0_ANA_CON2,
	CSI2PHY_COMBO_S0D0_ANA_CON3,
	CSI2PHY_COMBO_S0D0_ANA_CON6,
	CSI2PHY_COMBO_S0D0_ANA_CON7,
	CSI2PHY_COMBO_S0D0_DESKEW_CON0,
	CSI2PHY_COMBO_S0D0_DESKEW_CON2,
	CSI2PHY_COMBO_S0D0_DESKEW_CON4,
	CSI2PHY_COMBO_S0D0_CRC_CON1,
	CSI2PHY_COMBO_S0D0_CRC_CON2,
	CSI2PHY_COMBO_S0D1_GNR_CON1,
	CSI2PHY_COMBO_S0D1_ANA_CON1,
	CSI2PHY_COMBO_S0D1_ANA_CON2,
	CSI2PHY_COMBO_S0D1_ANA_CON3,
	CSI2PHY_COMBO_S0D1_ANA_CON6,
	CSI2PHY_COMBO_S0D1_ANA_CON7,
	CSI2PHY_COMBO_S0D1_DESKEW_CON0,
	CSI2PHY_COMBO_S0D1_DESKEW_CON2,
	CSI2PHY_COMBO_S0D1_DESKEW_CON4,
	CSI2PHY_COMBO_S0D1_CRC_CON1,
	CSI2PHY_COMBO_S0D1_CRC_CON2,
	CSI2PHY_COMBO_S0D2_GNR_CON1,
	CSI2PHY_COMBO_S0D2_ANA_CON1,
	CSI2PHY_COMBO_S0D2_ANA_CON2,
	CSI2PHY_COMBO_S0D2_ANA_CON3,
	CSI2PHY_COMBO_S0D2_ANA_CON6,
	CSI2PHY_COMBO_S0D2_ANA_CON7,
	CSI2PHY_COMBO_S0D2_DESKEW_CON0,
	CSI2PHY_COMBO_S0D2_DESKEW_CON2,
	CSI2PHY_COMBO_S0D2_DESKEW_CON4,
	CSI2PHY_COMBO_S0D2_CRC_CON1,
	CSI2PHY_COMBO_S0D2_CRC_CON2,
	CSI2PHY_S0D3_GNR_CON1,
	CSI2PHY_S0D3_ANA_CON1,
	CSI2PHY_S0D3_ANA_CON2,
	CSI2PHY_S0D3_ANA_CON3,
	CSI2PHY_S0D3_DESKEW_CON0,
	CSI2PHY_S0D3_DESKEW_CON2,
	CSI2PHY_S0D3_DESKEW_CON4,
};

#define HIWORD_UPDATE(val, mask, shift) \
		((val) << (shift) | (mask) << ((shift) + 16))

#define GRF_REG(_offset, _width, _shift) \
	{ .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, }

#define CSI2PHY_REG(_offset) \
	{ .offset = _offset, }

/* add new chip id in tail by time order */
enum csi2_dphy_chip_id {
	CHIP_ID_RK3568 = 0x0,
	CHIP_ID_RK3588 = 0x1,
	CHIP_ID_RK3588_DCPHY = 0x2,
	CHIP_ID_RV1106 = 0x3,
	CHIP_ID_RK3562 = 0x4,
};

enum csi2_dphy_rx_pads {
	CSI2_DPHY_RX_PAD_SINK = 0,
	CSI2_DPHY_RX_PAD_SOURCE,
	CSI2_DPHY_RX_PADS_NUM,
};

enum csi2_dphy_lane_mode {
	LANE_MODE_UNDEF = 0x0,
	LANE_MODE_FULL,
	LANE_MODE_SPLIT,
};

struct grf_reg {
	u32 offset;
	u32 mask;
	u32 shift;
};

struct csi2dphy_reg {
	u32 offset;
};

struct hsfreq_range {
	u32 range_h;
	u16 cfg_bit;
};

#define MAX_DPHY_SENSORS	(2)
#define MAX_NUM_CSI2_DPHY	(0x2)

#define RKCSI2_MAX_RESET 8
#define RKDPHY_MAX_RESET 8
/* csi2 head */

struct csi2_dphy_hw {
	struct	clk_bulk_data *dphy_clks;
	int num_dphy_clks;
	struct	clk_bulk_data *csi2_clks;
	int num_csi2_clks;
	const char * const *csi2_rsts;
	struct reset_control *csi2_rst[RKCSI2_MAX_RESET];
	int num_csi2_rsts;
	const char * const *dphy_rsts;
	struct reset_control *dphy_rst[RKDPHY_MAX_RESET];
	int num_dphy_rsts;
	// struct reset_control	*rsts_bulk;
	/*  spinlock_t lock; */
	bool on;
	const struct hsfreq_range *hsfreq_ranges;
	int num_hsfreq_ranges;
	const struct grf_reg *grf_regs;
	const struct txrx_reg *txrx_regs;
	const struct csi2dphy_reg *csi2dphy_regs;
	enum csi2_dphy_chip_id chip_id;
	struct device *dev;
	struct regmap *regmap_grf;
	struct regmap *regmap_sys_grf;
	void __iomem	*csi2_dphy_base; /*csi2_dphy base addr*/
	void __iomem	*csi2_base; /*csi2 base addr*/
	struct mutex mutex; /* lock for updating protection */
	atomic_t stream_cnt;
	struct csi2_err_stats err_list[RK_CSI2_ERR_MAX];
	u64 data_rate_mbps;
	struct rkmodule_csi_dphy_param *dphy_param;
	struct samsung_mipi_dcphy *samsung_phy;
	int phy_index;
};

#endif
